home *** CD-ROM | disk | FTP | other *** search
- /*************************************************************
- Copyright (C) 1990, 1991, 1993 Andy C. Hung, all rights reserved.
- PUBLIC DOMAIN LICENSE: Stanford University Portable Video Research
- Group. If you use this software, you agree to the following: This
- program package is purely experimental, and is licensed "as is".
- Permission is granted to use, modify, and distribute this program
- without charge for any purpose, provided this license/ disclaimer
- notice appears in the copies. No warranty or maintenance is given,
- either expressed or implied. In no event shall the author(s) be
- liable to you or a third party for any special, incidental,
- consequential, or other damages, arising out of the use or inability
- to use the program for any purpose (or the loss of data), even if we
- have been advised of such possibilities. Any public reference or
- advertisement of this source code should refer to it as the Portable
- Video Research Group (PVRG) code, and not by any author(s) (or
- Stanford University) name.
- *************************************************************/
- /*
- ************************************************************
- ppm2cyuv.c
-
- This program separates a raw ppm input file into component YUV files
- with a sampling ratio of 4:1:1 (the same pattern as MPEG 4:2:0). The
- output is placed in .Y .U .V by default.
-
- The ppm description and files are part of Jef Poskanzer's PBMPLUS
- library. This is just a short-cut program to do a simple YUV
- conversion.
-
- -----
- Modifications by Son H. Le on 01-Sep-93
- o replaced all exit(-1) with exit(0)
- o added exit(0) after convertRGB2YUV()
- o added #include <stdlib.h> and <string.h>
- o added prototype convertRGB2YUV()
- ************************************************************
- */
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
-
- #define PPM_MAGIC1 'P'
- #define PPM_MAGIC2 '3'
- #define RPPM_MAGIC2 '6'
- #define FIXNUM 16
-
- #define FIX(a,b) ((int)((a)*(1<<(b))))
- #define UNFIX(a,b) ((a+(1<<(b-1)))>>(b))
-
- /* Approximate 255 by 256 */
- #define CCIRUV(x) (((((x)-128)*224)>>8)+128)
- #define CCIRY(x) (((((x))*219)>>8)+16)
-
- #define CLIP(t) (((t)>255)?255:(((t)<0)?0:(t)))
- #define GETY(r,g,b) UNFIX((FIX(0.299,FIXNUM)*(r)+\
- FIX(0.587,FIXNUM)*(g)+\
- FIX(0.144,FIXNUM)*(b)),FIXNUM)
- #define GETU(r,g,b) UNFIX((FIX(-0.1687,FIXNUM)*(r)+\
- FIX(-0.3313,FIXNUM)*(g)+\
- FIX(0.5,FIXNUM)*(b)),FIXNUM)
- #define GETV(r,g,b) UNFIX((FIX(0.5,FIXNUM)*(r)+\
- FIX(-0.4187,FIXNUM)*(g)+\
- FIX(-0.0813,FIXNUM)*(b)),FIXNUM)
-
- char *suffix[3] = {".Y",".U",".V"};
-
- void convertRGB2YUV(FILE *inp,FILE *outy, FILE *outu,FILE *outv, int CCIR601);
-
- void
- convertRGB2YUV(inp, outy, outu, outv, CCIR601)
- FILE *inp,*outy,*outu,*outv;
- int CCIR601;
- {
- int i,j;
- int r1,r2,r3,r4,g1,g2,g3,g4,b1,b2,b3,b4;
- int magic1, magic2;
- int incols,inrows,maxval;
- int outcols,outrows;
- int temp;
- char inpstring[256];
- unsigned char *temprgb1, *temprgb2, *tempy1, *tempy2, *tempu, *tempv;
- unsigned char *rgb1p, *rgb2p, *y1p, *y2p, *up, *vp;
-
- magic1=fgetc(inp);
- magic2=fgetc(inp);
- fgetc(inp); /* dispense with \n */
- fgets(inpstring,256,inp);
- sscanf(inpstring,"%d %d",&incols, &inrows);
- fgets(inpstring,256,inp);
- sscanf(inpstring,"%d",&maxval);
-
- /* printf("%d %d %d %d %d\n",magic1,magic2,incols,inrows,maxval); */
- if (maxval>255)
- {
- printf("Only handles maximum value of 255 < (found)%d\n",maxval);
- exit(0);
- }
- if (magic1 != PPM_MAGIC1)
- {
- printf("Bad magic number 1; not ppm file?\n");
- exit(0);
- }
- if (magic2 != RPPM_MAGIC2)
- {
- printf("Bad magic number 2; not raw ppm file?\n");
- exit(0);
- }
-
- if (inrows&1) outrows = inrows-1;
- else outrows = inrows;
- if (incols&1) outcols = incols-1;
- else outcols = incols;
-
- printf("input size: %dx%d\t output size: %dx%d\n",
- incols,inrows,outcols,outrows);
-
- temprgb1 = (unsigned char *) calloc(incols*3,sizeof(char));
- temprgb2 = (unsigned char *) calloc(incols*3,sizeof(char));
- tempy1 = (unsigned char *) calloc(outcols,sizeof(char));
- tempy2 = (unsigned char *) calloc(outcols,sizeof(char));
- tempu = (unsigned char *) calloc(outcols>>1,sizeof(char));
- tempv = (unsigned char *) calloc(outcols>>1,sizeof(char));
-
- for(i=0;i<(outrows>>1);i++)
- {
- fread(temprgb1,1,incols*3*sizeof(char),inp);
- fread(temprgb2,1,incols*3*sizeof(char),inp);
- rgb1p = temprgb1;
- rgb2p = temprgb2;
-
- y1p = tempy1;
- y2p = tempy2;
- up = tempu;
- vp = tempv;
-
- for(j=0;j<(outcols>>1);j++)
- {
- r1 = *(rgb1p++);
- g1 = *(rgb1p++);
- b1 = *(rgb1p++);
- r2 = *(rgb1p++);
- g2 = *(rgb1p++);
- b2 = *(rgb1p++);
-
- r3 = *(rgb2p++);
- g3 = *(rgb2p++);
- b3 = *(rgb2p++);
- r4 = *(rgb2p++);
- g4 = *(rgb2p++);
- b4 = *(rgb2p++);
-
- if (CCIR601)
- {
- temp=GETY(r1,g1,b1);
- temp=CLIP(temp);
- *(y1p++) = CCIRY(temp);
- temp=GETY(r2,g2,b2);
- temp=CLIP(temp);
- *(y1p++) = CCIRY(temp);
- temp=GETY(r3,g3,b3);
- temp=CLIP(temp);
- *(y2p++) = CCIRY(temp);
- temp=GETY(r4,g4,b4);
- temp=CLIP(temp);
- *(y2p++) = CCIRY(temp);
-
- /* We use a box filter for decimation */
-
- temp = ((GETU(r1+r2+r3+r4,g1+g2+g3+g4,b1+b2+b3+b4)
- +(1<<9)+(1<<1))>>2);
- temp=CLIP(temp);
- *(up++) = CCIRUV(temp);
- temp = ((GETV(r1+r2+r3+r4,g1+g2+g3+g4,b1+b2+b3+b4)
- +(1<<9)+(1<<1))>>2);
- temp=CLIP(temp);
- *(vp++) = CCIRUV(temp);
- }
- else
- {
- temp=GETY(r1,g1,b1);
- *(y1p++) = CLIP(temp);
- temp=GETY(r2,g2,b2);
- *(y1p++) = CLIP(temp);
- temp=GETY(r3,g3,b3);
- *(y2p++) = CLIP(temp);
- temp=GETY(r4,g4,b4);
- *(y2p++) = CLIP(temp);
-
- /* We use a box filter for decimation */
-
- temp = ((GETU(r1+r2+r3+r4,g1+g2+g3+g4,b1+b2+b3+b4)
- +(1<<9)+(1<<1))>>2);
- *(up++) = CLIP(temp);
- temp = ((GETV(r1+r2+r3+r4,g1+g2+g3+g4,b1+b2+b3+b4)
- +(1<<9)+(1<<1))>>2);
- *(vp++) = CLIP(temp);
- }
- }
- fwrite(tempy1,1,outcols*sizeof(char),outy);
- fwrite(tempy2,1,outcols*sizeof(char),outy);
- fwrite(tempu,1,(outcols>>1)*sizeof(char),outu);
- fwrite(tempv,1,(outcols>>1)*sizeof(char),outv);
- }
- }
-
- int
- main(argc, argv)
- int argc;
- char **argv;
-
- {
- int i;
- int CCIR601=0;
- int suffixcount=0;
- char *infile,*outfile;
- char outfiley[256];
- char outfileu[256];
- char outfilev[256];
- FILE *inp,*outy,*outu,*outv;
-
- if (argc<3)
- {
- printf("ppm2cyuv infile outfile [-z suffix]* [-CCIR601]\n");
- printf("\n");
- printf("infile is the input ppm file\n");
- printf("outfile is the output file with outfile.Y outfile.U outfile.V\n");
- printf("-z specifies alternate suffixes:\n");
- printf(" e.g. ppm2cyuv inp.ppm out -z .y -z .cb -z .cr\n");
- printf(" will output out.y, out.cb, out.cr, respectively\n");
- printf("-CCIR601 specifies CCIR601 yuv space (default JFIF).\n");
- exit(0);
- }
-
- for(i=3;i<argc;i++)
- {
- if (!strcmp(argv[i],"-z"))
- {
- if (suffixcount==3)
- {
- printf("too many suffixes\n");
- exit(0);
- }
- suffix[suffixcount++] = argv[++i];
- }
- else if (!strcmp(argv[i],"-CCIR601"))
- CCIR601=1;
- else
- {
- printf("unknown option: %s\n",argv[i]);
- exit(0);
- }
- }
-
- infile = argv[1];
- outfile = argv[2];
- sprintf(outfiley,"%s%s",outfile,suffix[0]);
- sprintf(outfileu,"%s%s",outfile,suffix[1]);
- sprintf(outfilev,"%s%s",outfile,suffix[2]);
-
- if (!(inp=fopen(infile,"r")))
- {
- printf("cannot open file: %s\n",infile);
- exit(0);
- }
- if (!(outy=fopen(outfiley,"w")))
- {
- printf("cannot open file: %s\n",outfiley);
- exit(0);
- }
- if (!(outu=fopen(outfileu,"w")))
- {
- printf("cannot open file: %s\n",outfileu);
- exit(0);
- }
- if (!(outv=fopen(outfilev,"w")))
- {
- printf("cannot open file: %s\n",outfilev);
- exit(0);
- }
- convertRGB2YUV(inp,outy,outu,outv,CCIR601);
- exit(0);
- }
-